home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * *
- * sortcomp.c version 1.0 of 1 Januari 1989 (C) L.J.M. de Wit 1989 *
- * *
- * This software may be used and distributed freely if not used commercially *
- * and the originator (me) is mentioned in the source (just leave this 9 line *
- * header intact). *
- * *
- ******************************************************************************
- *
- * sortcomp.c: comparision functions
- *
- * These functions contain the numeric comparision functions c_n and its
- * reverse, c_nr. The other 48 comparision functions are formed by combining
- * the following properties (take note of the Capitals):
- * a) either Dictionary, Ignore non-printables or Any other (3)
- * b) ignore leading Blanks, versus not ignoring them (2)
- * c) Fold upper case to lower, versus not folding (2)
- * d) Reverse the result of the comparision, versus not reversing (2)
- * e) Unbounded (bounded only by '\0'), versus upper limit bound (2)
- *
- * Since comparing is done a lot it is important for the compare functions
- * to be fast. As for using the 48 functions as it stands the following
- * arguments are used:
- * One could have combined functions and used flags to discern between options.
- * This would however involve passing more parameters to the function (the
- * flags) and would require (perhaps a lot of) unwanted testing inside the
- * function.
- * Several functions call one of the other functions. This has been done in
- * such a way that duplication of code is mostly prevented, but still this call
- * is limited to only one (both in number and in level).
- * The numerical compare could have been done by a simple atoi(), but the
- * c_n function does the comparision inline, and stops comparing when the
- * bigger one has been found (while atoi needs to do calculation ala
- * 10 * num + digit, and will use all digits).
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "sortmain.h"
- #include "sortcomp.h"
-
- #define SKIPSPACE(bs,bt) while (wspace(*(bs))) (bs)++; while (wspace(*(bt))) (bt)++
-
- #define NCHARS 256
- #define NORM 0x1
- #define DICT 0x2
- #define isnorm(c) (stype[(c)]&NORM)
- #define isdict(c) (stype[(c)]&DICT)
-
- #undef isdigit
- #define isdigit(c) ((c) >= '0' && (c) <= '9')
-
- static char fold[NCHARS]; /* For lcase conversion */
-
- static char stype[NCHARS]; /* For table lookup */
-
- void initlookup() /* Initialize lookup tables */
- {
- register int i;
-
- for (i = 0; i < NCHARS; i++) {
- fold[i] = isupper(i) ? tolower(i) : i; /* Init lcase convert array */
- stype[i] = 0; /* Not really needed ... */
- if (i >= 040 && i <= 0176) { /* Ascii non-control */
- stype[i] |= NORM;
- }
- if (wspace(i) || isalnum(i)) { /* Whitespace & alphanum */
- stype[i] |= DICT;
- }
- }
- }
-
- int c_nr(bs,bt,es,et) /* Reversed Numeric */
- char *bs, *bt;
- char *es, *et;
- {
- return c_n(bt,bs,et,es);
- }
-
- int c_n(bs,bt,es,et) /* Numeric compare */
- register char *bs, *bt;
- char *es, *et;
- {
- register int rev, mini;
-
- SKIPSPACE(bs,bt);
- if (*bs == '-') {
- if (*bt == '-') { /* Two negatives: reverse */
- rev = -1;
- bs++;
- bt++;
- } else { /* bt will be the larger one*/
- return -1;
- }
- } else {
- if (*bt == '-') { /* bs will be the larger one*/
- return 1;
- } else {
- rev = 1; /* Both positive */
- }
- }
-
- while (*bs == *bt && isdigit(*bt)) { /* Compare & skip eq. digits*/
- bs++; bt++;
- }
-
- if (!isdigit(*bs)) {
- if (!isdigit(*bt)) {
- if (*bs == '.' && *bt == '.') { /* Decimal point */
- while (*++bs == *++bt && isdigit(*bt)) ;
- while (*bs == '0') bs++; /* Skip possibly trailing */
- while (*bt == '0') bt++; /* zeroes */
- if (!isdigit(*bs)) {
- if (!isdigit(*bt)) {
- return 0; /* Tails also equal */
- }
- return -rev; /* bt has more digits */
- }
- if (!isdigit(*bt)) {
- return rev; /* bs has more digits */
- }
- return (rev == 1) /* Current digit decides */
- ? (*bs - *bt) : (*bt - *bs);
- } else {
- return 0; /* Equal numeric strings */
- }
- }
- return -rev; /* bt has more digits */
- }
- if (!isdigit(*bt)) {
- return rev; /* bs has more digits */
- }
- mini = (rev == 1) /* Current digit decides: */
- ? (*bs - *bt) : (*bt - *bs); /* Difference into mini */
- do {
- bs++;
- bt++;
- } while (isdigit(*bs) && isdigit(*bt)); /* Skip any more digits */
-
- if (!isdigit(*bs)) {
- if (!isdigit(*bt)) { /* Strings equally long: */
- return mini; /* then mini decides */
- }
- return -rev; /* bt has more digits */
- }
- return rev; /* bs has more digits */
- }
-
- int c_df(bs,bt,es,et) /* Dictionary/Fold */
- register char *bs, *bt; /* Strings to compare */
- register char *es, *et;
- {
- --bs; --bt; --es; --et;
- for ( ; bs < es && bt < et; ) {
- if (fold[*++bs] != fold[*++bt]) { /* Increment & compare */
- if (isdict(*bs)) {
- if (isdict(*bt)) {
- return fold[*bs] - fold[*bt];
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else if (isdict(*bt)) {
- --bt; /* Effectively skip *bs */
- } /* (else: skip both) */
- }
- }
- for ( ; bs < es; ) { /* Skip any more */
- if (isdict(*++bs)) { /* non-dict chars in bs */
- --bs;
- break;
- }
- }
- for ( ; bt < et; ) { /* Skip any more */
- if (isdict(*++bt)) { /* non-dict chars in bt */
- --bt;
- break;
- }
- }
-
- return (et - bt) - (es - bs);
- }
-
- int c_d(bs,bt,es,et) /* Dictionary order */
- register char *bs, *bt;
- register char *es, *et;
- {
- --bs; --bt; --es; --et;
- for ( ; bs < es && bt < et; ) {
- if (*++bs != *++bt) { /* Increment & compare */
- if (isdict(*bs)) {
- if (isdict(*bt)) {
- return fold[*bs] - fold[*bt];
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else if (isdict(*bt)) {
- --bt; /* Effectively skip *bs */
- } /* (else: skip both) */
- }
- }
- for ( ; bs < es; ) { /* Skip any more */
- if (isdict(*++bs)) { /* non-dict chars in bs */
- --bs;
- break;
- }
- }
- for ( ; bt < et; ) { /* Skip any more */
- if (isdict(*++bt)) { /* non-dict chars in bt */
- --bt;
- break;
- }
- }
-
- return (et - bt) - (es - bs);
- }
-
- int c_if(bs,bt,es,et) /* Normalized/Fold */
- register char *bs, *bt;
- register char *es, *et;
- {
- --bs; --bt; --es; --et;
- for ( ; bs < es && bt < et; ) {
- if (fold[*++bs] != fold[*++bt]) { /* Increment & compare */
- if (isnorm(*bs)) {
- if (isnorm(*bt)) {
- return fold[*bs] - fold[*bt];
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else if (isnorm(*bt)) {
- --bt; /* Effectively skip *bs */
- } /* (else: skip both) */
- }
- }
- for ( ; bs < es; ) { /* Skip any more */
- if (isnorm(*++bs)) { /* non-norm chars in bs */
- --bs;
- break;
- }
- }
- for ( ; bt < et; ) { /* Skip any more */
- if (isnorm(*++bt)) { /* non-norm chars in bt */
- --bt;
- break;
- }
- }
-
- return (et - bt) - (es - bs);
- }
-
- int c_i(bs,bt,es,et) /* Normalized order */
- register char *bs, *bt;
- register char *es, *et;
- {
- --bs; --bt; --es; --et;
- for ( ; bs < es && bt < et; ) {
- if (*++bs != *++bt) { /* Increment & compare */
- if (isnorm(*bs)) {
- if (isnorm(*bt)) {
- return fold[*bs] - fold[*bt];
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else if (isnorm(*bt)) {
- --bt; /* Effectively skip *bs */
- } /* (else: skip both) */
- }
- }
- for ( ; bs < es; ) { /* Skip any more */
- if (isnorm(*++bs)) { /* non-norm chars in bs */
- --bs;
- break;
- }
- }
- for ( ; bt < et; ) { /* Skip any more */
- if (isnorm(*++bt)) { /* non-norm chars in bt */
- --bt;
- break;
- }
- }
-
- return (et - bt) - (es - bs);
- }
-
- int c_af(bs,bt,es,et) /* Fold */
- register char *bs, *bt;
- register char *es, *et;
- {
- register short minlen;
-
- minlen = ((es - bs) <= (et - bt)) ? (es - bs) : (et - bt);
- if (minlen == 0) {
- return (es - bs) - (et - bt);
- }
-
- if (fold[*bs] == fold[*bt]) {
- for ( ; --minlen != 0 && fold[*++bs] == fold[*++bt]; ) ;
- if (minlen == 0) {
- return 0;
- }
- }
-
- return fold[*bs] - fold[*bt];
- }
-
- int c_dfu(bs,bt) /* Dictionary/Fold */
- register char *bs, *bt;
- {
- register char *fld = fold;
-
- --bs; --bt;
- do {
- while (fld[*++bs] == fld[*++bt] && *bt) ; /* Skip equal ones */
- if (!*bt || !*bs) break; /* Stop on '\0' */
- if (isdict(*bs)) {
- if (isdict(*bt)) {
- break; /* Difference found */
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else {
- if (isdict(*bt)) {
- --bt; /* Effectively skip *bs */
- }
- } /* (else: skip both) */
- } while (1);
-
- return fld[*bs] - fld[*bt];
- }
-
- int c_du(bs,bt) /* Dictionary */
- register char *bs, *bt;
- {
- --bs; --bt;
- do {
- while (*++bs == *++bt && *bt) ; /* Skip equal ones */
- if (!*bt || !*bs) break; /* Stop on '\0' */
- if (isdict(*bs)) {
- if (isdict(*bt)) {
- break; /* Difference found */
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else {
- if (isdict(*bt)) {
- --bt; /* Effectively skip *bs */
- }
- } /* (else: skip both) */
- } while (1);
-
- return *bs - *bt;
- }
-
- int c_ifu(bs,bt) /* Normalized/Fold */
- register char *bs, *bt;
- {
- register char *fld = fold;
-
- --bs; --bt;
- do {
- while (fld[*++bs] == fld[*++bt] && *bt) ; /* Skip equal ones */
- if (!*bt || !*bs) break; /* Stop on '\0' */
- if (isnorm(*bs)) {
- if (isnorm(*bt)) {
- break; /* Difference found */
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else {
- if (isnorm(*bt)) {
- --bt; /* Effectively skip *bs */
- }
- } /* (else: skip both) */
- } while (1);
-
- return fld[*bs] - fld[*bt];
- }
-
- int c_iu(bs,bt) /* Normalized */
- register char *bs, *bt;
- {
- --bs; --bt;
- do {
- while (*++bs == *++bt && *bt) ; /* Skip equal ones */
- if (!*bt || !*bs) break; /* Stop on '\0' */
- if (isnorm(*bs)) {
- if (isnorm(*bt)) {
- break; /* Difference found */
- } else {
- --bs; /* Effectively skip *bt */
- }
- } else {
- if (isnorm(*bt)) {
- --bt; /* Effectively skip *bs */
- }
- } /* (else: skip both) */
- } while (1);
-
- return *bs - *bt;
- }
-
- int c_afu(bs,bt) /* Fold */
- register char *bs, *bt;
- {
- register char *fld = fold;
-
- if (fld[*bs] == fld[*bt] && *bt) {
- for ( ; fld[*++bs] == fld[*++bt] && *bt; ) ;
- }
-
- return fld[*bs] - fld[*bt];
- }
-
- #ifndef M68000
- /* using asm if 68000 */
-
- int c_dbfr(bs,bt,es,et) /* Dict/Blank/Fold/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_df(bt,bs,et,es);
- }
-
- int c_dbf(bs,bt,es,et) /* Dictionary/Blank/Fold */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_df(bs,bt,es,et);
- }
-
- int c_dbr(bs,bt,es,et) /* Dictionary/Blank/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_d(bt,bs,et,es);
- }
-
- int c_db(bs,bt,es,et) /* Dictionary/Blank */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_d(bs,bt,es,et);
- }
-
- int c_dfr(bs,bt,es,et) /* Dictionary/Fold/Reverse */
- char *bs, *bt;
- char *es, *et;
- {
- return c_df(bt,bs,et,es);
- }
-
- int c_dr(bs,bt,es,et) /* Dictionary/Reversed */
- char *bs, *bt;
- char *es, *et;
- {
- return c_d(bt,bs,et,es);
- }
-
- int c_ibfr(bs,bt,es,et) /* Norm/Blank/Fold/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_if(bt,bs,et,es);
- }
-
- int c_ibf(bs,bt,es,et) /* Normalized/Blank/Fold */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_if(bs,bt,es,et);
- }
-
- int c_ibr(bs,bt,es,et) /* Normalized/Blank/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_i(bt,bs,et,es);
- }
-
- int c_ib(bs,bt,es,et) /* Normalized/Blank */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_i(bs,bt,es,et);
- }
-
- int c_ifr(bs,bt,es,et) /* Normalized/Fold/Reverse */
- char *bs, *bt;
- char *es, *et;
- {
- return c_if(bt,bs,et,es);
- }
-
- int c_ir(bs,bt,es,et) /* Normalized/Reversed */
- char *bs, *bt;
- char *es, *et;
- {
- return c_i(bt,bs,et,es);
- }
-
- int c_abfr(bs,bt,es,et) /* Blank/Fold/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_af(bt,bs,et,es);
- }
-
- int c_abf(bs,bt,es,et) /* Blank/Fold */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_af(bs,bt,es,et);
- }
-
- int c_abr(bs,bt,es,et) /* Blank/Reverse */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_a(bt,bs,et,es);
- }
-
- int c_ab(bs,bt,es,et) /* Blank */
- register char *bs, *bt;
- char *es, *et;
- {
- SKIPSPACE(bs,bt);
- return c_a(bs,bt,es,et);
- }
-
- int c_afr(bs,bt,es,et) /* Fold/Reverse */
- char *bs, *bt;
- char *es, *et;
- {
- return c_af(bt,bs,et,es);
- }
-
- int c_ar(bs,bt,es,et) /* Reverse */
- char *bs, *bt;
- char *es, *et;
- {
- return c_a(bt,bs,et,es);
- }
-
- /* Unbounded comparisions start here */
-
- int c_dbfru(bs,bt) /* Dict/Blank/Fold/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_dfu(bt,bs);
- }
-
- int c_dbfu(bs,bt) /* Dictionary/Blank/Fold */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_dfu(bs,bt);
- }
-
- int c_dbru(bs,bt) /* Dictionary/Blank/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_du(bt,bs);
- }
-
- int c_dbu(bs,bt) /* Dictionary/Blank */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_du(bs,bt);
- }
-
- int c_dfru(bs,bt) /* Dictionary/Fold/Reverse */
- char *bs, *bt;
- {
- return c_dfu(bt,bs);
- }
-
- int c_dru(bs,bt) /* Dictionary/Reverse */
- char *bs, *bt;
- {
- return c_du(bt,bs);
- }
-
- int c_ibfru(bs,bt) /* Norm/Blank/Fold/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_ifu(bt,bs);
- }
-
- int c_ibfu(bs,bt) /* Normalized/Blank/Fold */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_ifu(bs,bt);
- }
-
- int c_ibru(bs,bt) /* Normalized/Blank/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_iu(bt,bs);
- }
-
- int c_ibu(bs,bt) /* Normalized/Blank */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_iu(bs,bt);
- }
-
- int c_ifru(bs,bt) /* Normalized/Fold/Reverse */
- char *bs, *bt;
- {
- return c_ifu(bt,bs);
- }
-
- int c_iru(bs,bt) /* Normalized/Reverse */
- char *bs, *bt;
- {
- return c_iu(bt,bs);
- }
-
- int c_abfru(bs,bt) /* Blank/Fold/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_afu(bt,bs);
- }
-
- int c_abfu(bs,bt) /* Blank/Fold */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_afu(bs,bt);
- }
-
- int c_abru(bs,bt) /* Blank/Reverse */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_au(bt,bs);
- }
-
- int c_abu(bs,bt) /* Blank */
- register char *bs, *bt;
- {
- SKIPSPACE(bs,bt);
- return c_au(bs,bt);
- }
-
- int c_afru(bs,bt) /* Fold/Reverse */
- register char *bs, *bt;
- {
- register char *fld = fold;
-
- if (fld[*bs] == fld[*bt] && *bt) {
- for ( ; fld[*++bs] == fld[*++bt] && *bt; ) ;
- }
-
- return fld[*bt] - fld[*bs];
- }
-
- int c_aru(bs,bt) /* Reverse */
- register char *bs, *bt;
- {
- if (*bs == *bt && *bt) {
- for ( ; *++bs == *++bt && *bt; ) ;
- }
-
- return *bt - *bs;
- }
-
- int c_au(bs,bt) /* Ordinary sort */
- register char *bs, *bt;
- {
- if (*bs == *bt && *bs) { /* Compare & skip eq. chars */
- while (*++bs == *++bt && *bs) ; /* Compare & skip eq. chars */
- }
-
- return *bs - *bt;
- }
-
- int c_a(bs,bt,es,et) /* Ordinary sort */
- register char *bs, *bt;
- register char *es, *et;
- {
- register short minlen;
-
- minlen = ((es - bs) <= (et - bt)) ? (es - bs) : (et - bt);
- if (minlen == 0) {
- return (es - bs) - (et - bt);
- }
-
- if (*bs == *bt) {
- for ( ; --minlen != 0 && *++bs == *++bt; ) ;
- if (minlen == 0) {
- return 0;
- }
- }
-
- return *bs - *bt;
- }
- #endif not MC68000
-